﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MapAppLearning.GeocodeService;
using MapAppLearning.SearchService;
using MapAppLearning.ImageryService;
using MapAppLearning.RouteService;
using System.Text.RegularExpressions;
using System.Threading;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using SmartRoute.Data;




namespace MapAppLearning
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        DataModule testModule;
        Genetics testGenetics;
        int zoomLevel;
        double offsetX;
        double offsetY;
        String[] stops;
        public Window1()
        {
            try
            {
                InitializeComponent();
            }
            catch (Exception ex)
            {
                int i = 0;
            }
            offsetX = 0;
            offsetY = 0;

            /* = new String[15]
            {   "509 w 13th ave, Ellensburg",
                "103 W Courtney Ct, Ellensburg",
                "1302 South Ruby Street, Ellensburg",
                "1210 S Canyon Rd, Ellensburg",
                "509 W 13th Ave, Ellensburg",
                "1880 Vantage Hwy, Ellensburg",
                //"2080 Vantage Hwy, Ellensburg",
                //"1880 Vantage Hwy, Ellensburg",
                //"2080 Vantage Hwy, Ellensburg",
                //"2680 Vantage Hwy, Ellensburg", 
                //"3240 Kittitas Hwy, Ellensburg",
                "3150 Kittitas Hwy, Ellensburg",
                "2451 N Ferguson Rd, Ellensburg",
                "2781 Kittitas Hwy, Ellensburg",
                //"1533 Kittitas Hwy, Ellensburg",
                "705 S Matthews Rd, Ellensburg",
                "2851 4th Parallel Rd, Ellensburg",
                //"1220 4th Parallel Rd, Ellensburg",
                //"550 4th Parallel Rd, Ellensburg",
                "6883 Denmark Rd, Ellensburg",
                "1641 Payne Rd, Ellensburg",
                //"2211 Payne Rd, Ellensburg",
                //"2371 Payne Rd, Ellensburg",
                //"1738 Payne Rd, Ellensburg",
                //"540 Payne Rd, Ellensburg",
                "1201 Orchard Rd, Ellensburg",
                "100 N Main, Ellesburg"    };
             * */
            /*
            testModule = new DataModule();
            testModule.addBoundary(stops);

            testGenetics = new Genetics(100, 5, 15, 50, 3600, testModule.accessMap(0));

            testGenetics.setMap(testModule.accessMap(0).Stops);
            testGenetics.setShortestDistanceArray(testModule.accessMap(0).ShortestDistanceArrayTime);

            testGenetics.initializeGeneArray();

            testGenetics.run(1);
             * */

            stops = new String[15];







        }





        //this method was found on http://msdn.microsoft.com/en-us/library/dd221354.aspx
        private static string PrintRoute(RouteResponse route)
        {
            string results = "";
            RouteResponse routeResponse = route;

            // Iterate through each itinerary item to get the route directions
            StringBuilder directions = new StringBuilder("");

            if (routeResponse.Result.Legs.Length > 0)
            {
                int instructionCount = 0;
                int legCount = 0;

                foreach (RouteLeg leg in routeResponse.Result.Legs)
                {
                    legCount++;
                    directions.Append(string.Format("Leg #{0}\n", legCount));

                    foreach (ItineraryItem item in leg.Itinerary)
                    {
                        instructionCount++;
                        directions.Append(string.Format("{0}. {1}\n",
                            instructionCount, item.Text));
                    }
                }
                //Remove all Bing Maps tags around keywords.  
                //If you wanted to format the results, you could use the tags
                Regex regex = new Regex("<[/a-zA-Z:]*>",
                  RegexOptions.IgnoreCase | RegexOptions.Multiline);
                results = regex.Replace(directions.ToString(), string.Empty);
            }
            else
                results = "No Route found";

            return results;
        }




        private void button1_Click(object sender, RoutedEventArgs e)
        {


        }


        private void button3_Click(object sender, RoutedEventArgs e)
        {


        }


        private void button4_Click(object sender, RoutedEventArgs e)
        {
            this.testGenetics.setRoutes();
            
            
            String key = "AhqjOSdmQlNyiAfMcr8HicreBdxgTnuVaiMGVFnP9x3l_12WQgLyV1pRrfIpECX5";
            MapUriRequest mapUriRequest = new MapUriRequest();

            // Set credentials using a valid Bing Maps key
            mapUriRequest.Credentials = new ImageryService.Credentials();
            mapUriRequest.Credentials.ApplicationId = key;

            // Set the location of the requested image
            mapUriRequest.Center = new ImageryService.Location();
            mapUriRequest.Center.Latitude = testModule.accessMap(0).Routes[0, 0].Result.Legs[0].ActualStart.Latitude + offsetX;
            mapUriRequest.Center.Longitude = testModule.accessMap(0).Routes[0, 0].Result.Legs[0].ActualStart.Longitude + offsetY;

            // Set the map style and zoom level
            MapUriOptions mapUriOptions = new MapUriOptions();
            mapUriOptions.Style = MapStyle.Road;
            mapUriOptions.ZoomLevel = zoomLevel;

            // Set the size of the requested image in pixels
            mapUriOptions.ImageSize = new ImageryService.SizeOfint();
            mapUriOptions.ImageSize.Height = 800;
            mapUriOptions.ImageSize.Width = 800;

            mapUriRequest.Options = mapUriOptions;




            // Set the location of the requested image
            MapAppLearning.ImageryService.Location initial = new MapAppLearning.ImageryService.Location();
            initial.Latitude = testModule.accessMap(0).Routes[0, 1].Result.Legs[0].ActualStart.Latitude;
            initial.Longitude = testModule.accessMap(0).Routes[0, 1].Result.Legs[0].ActualStart.Longitude;
            // Set the location of the requested image
            MapAppLearning.ImageryService.Location dest = new MapAppLearning.ImageryService.Location();
            dest.Latitude = testModule.accessMap(0).Routes[0, 1].Result.Legs[0].ActualEnd.Latitude;
            dest.Longitude = testModule.accessMap(0).Routes[0, 1].Result.Legs[0].ActualEnd.Longitude;

            //mapUriRequest.MajorRoutesDestination.Latitude = routes[0, 0].Result.Legs[0].ActualEnd.Latitude;
            //mapUriRequest.MajorRoutesDestination.Longitude = routes[0, 0].Result.Legs[0].ActualEnd.Longitude;



            //Make the request and return the URI
            ImageryServiceClient imageryService = new ImageryServiceClient("BasicHttpBinding_IImageryService");
            MapUriResponse mapUriResponse = imageryService.GetMapUri(mapUriRequest);
            label1.Visibility = Visibility.Hidden;
            imageResults.Visibility = Visibility.Visible;



            //Get URI and set image
            String imageURI = mapUriResponse.Uri;



            BitmapImage mapImage = new BitmapImage(new Uri(imageURI));
            imageResults.Source = mapImage;
            imageResults.Visibility = Visibility.Visible;
            Image image = new Image();
            image.Source = mapImage;

            //testing conversion of lat/lon into x/y pixel coordinates
            double EarthRadius = 6378137;

            this.canvas1.Children.Clear();
            //CENTER
            double latCent = mapUriRequest.Center.Latitude;
            double lonCent = mapUriRequest.Center.Longitude;

            double xc = (lonCent + 180) / 360;
            double sinLatC = Math.Sin(latCent * Math.PI / 180);
            double yc = .5 - Math.Log((1 + sinLatC) / (1 - sinLatC)) / (4 * Math.PI);
            int mapSize = 256 << zoomLevel; //14=levelOfdetail
            int pixelXC = (int)((xc * mapSize) + .5);
            int pixelYC = (int)((yc * mapSize) + .5);

            int xDiff = 422 - pixelXC;
            int yDiff = 400 - pixelYC;
            int debugCount = testModule.accessMap(0).ProducedByAlgorithm.Count;
            BitmapImage test = new BitmapImage();
            for (int j = 0; j < debugCount; j++)
            {
                for (int r = 0; r < testModule.accessMap(0).ProducedByAlgorithm[j].Length; r++)
                {

                        for (int w = 0; w < testModule.accessMap(0).ProducedByAlgorithm[j][r].Result.RoutePath.Points.Length-1; w++)
                        {
                            double lat = testModule.accessMap(0).ProducedByAlgorithm[j][r].Result.RoutePath.Points[w].Latitude;
                            double lon = testModule.accessMap(0).ProducedByAlgorithm[j][r].Result.RoutePath.Points[w].Longitude;

                            double latEnd = testModule.accessMap(0).ProducedByAlgorithm[j][r].Result.RoutePath.Points[w+1].Latitude;
                            double lonEnd = testModule.accessMap(0).ProducedByAlgorithm[j][r].Result.RoutePath.Points[w+1].Longitude;



                            //OTHER
                            double xStart = (lon + 180) / 360;
                            double sinLatStart = Math.Sin(lat * Math.PI / 180);
                            double yStart = .5 - Math.Log((1 + sinLatStart) / (1 - sinLatStart)) / (4 * Math.PI);


                            double xEnd = (lonEnd + 180) / 360;
                            double sinLatEnd = Math.Sin(latEnd * Math.PI / 180);
                            double yEnd = .5 - Math.Log((1 + sinLatEnd) / (1 - sinLatEnd)) / (4 * Math.PI);



                            int pixelX = (int)(xStart * mapSize + .5);
                            int pixelY = (int)(yStart * mapSize + .5);


                            int pixelXEnd = (int)(xEnd * mapSize + .5);
                            int pixelYEnd = (int)(yEnd * mapSize + .5);




                            /*
                            double width = 256 * Math.Pow(2, 1);
                            double height = width;
                            double resolution = (Math.Cos(dest.Latitude * Math.PI / 180)) * (2 * Math.PI * EarthRadius);

                            double x = ((initial.Longitude + 180) / 360) * width;
                            double sinLatitude = Math.Sin(initial.Latitude * Math.PI / 180);
                            double y = (.5 - Math.Log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))*width;
                            int mapSize = 256 << 1;
                            //return Math.Min(Math.Max(n, minValue), maxValue);

                            int pixelX = (int)Math.Min(Math.Max(x * mapSize + .5, 0), mapSize - 1);
                            int pixelY = (int)Math.Min(Math.Max(y * mapSize + .5, 0), mapSize - 1);

                            int pixelR = (int)(180 + dest.Longitude) * (512 / 360);
                            int pixelZ = (int)(90 - dest.Latitude) * (512 / 180);


                            double lat = Math.PI * dest.Latitude / 180;
                            double lon = Math.PI * dest.Longitude / 180;
                             * */

                            Line testLine = new Line();
                            testLine.X1 = pixelX + xDiff;
                            testLine.Y1 = pixelY + yDiff;
                            testLine.X2 = pixelXEnd + xDiff; ;
                            testLine.Y2 = pixelYEnd + yDiff;
                            SolidColorBrush myBrush = new SolidColorBrush();
                            if (j == 0)
                            {
                                myBrush.Color = Colors.Aqua;
                            }
                            if (j == 1)
                            {
                                myBrush.Color = Colors.Blue;
                            }
                            if (j == 2)
                            {
                                myBrush.Color = Colors.BlueViolet;
                            }
                            if (j == 3)
                            {
                                myBrush.Color = Colors.Aquamarine;
                            }
                            if (j == 4)
                            {
                                myBrush.Color = Colors.Chartreuse;
                            }
                            if (j == 5)
                            {
                                myBrush.Color = Colors.DarkOrange;
                            }
                            if (j == 6)
                            {
                                myBrush.Color = Colors.Fuchsia;
                            }
                            if (j == 7)
                            {
                                myBrush.Color = Colors.Firebrick;
                            }
                            if (j == 8)
                            {
                                myBrush.Color = Colors.DeepPink;
                            }
                            if (j == 9)
                            {
                                myBrush.Color = Colors.Teal;
                            }
                            if (j == 10)
                            {
                                myBrush.Color = Colors.Crimson;
                            }
                            if (j == 11)
                            {
                                myBrush.Color = Colors.Indigo;
                            }
                            if (j == 12)
                            {
                                myBrush.Color = Colors.Goldenrod;
                            }
                            if (j == 13)
                            {
                                myBrush.Color = Colors.Peru;
                            }
                            if (j == 14)
                            {
                                myBrush.Color = Colors.Plum;
                            }
                            if (j == 15)
                            {
                                myBrush.Color = Colors.Wheat;
                            }
                            if (j == 16)
                            {
                                myBrush.Color = Colors.Olive;
                            }
                            if (j == 17)
                            {
                                myBrush.Color = Colors.Green;
                            }
                            if (j == 18)
                            {
                                myBrush.Color = Colors.MediumSeaGreen;
                            }
                            if (j == 19)
                            {
                                myBrush.Color = Colors.Tan;
                            }
                            if (j == 20)
                            {
                                myBrush.Color = Colors.OrangeRed;
                            }


                            testLine.StrokeThickness = 1;
                            testLine.Stroke = myBrush;


                            canvas1.Children.Add(testLine);
                        }

                        

                        
                    
                }
            }

            String times = "";

            for (int i = 0; i < testModule.accessMap(0).ProducedByAlgorithm.Count; i++)
            {
                //sum up times for each bus
                int temp = 0;
                for(int j = 0; j < testModule.accessMap(0).ProducedByAlgorithm.Count; j++)
                {
                    
                    temp += (int)testModule.accessMap(0).ProducedByAlgorithm.ElementAt(i).ElementAt(j).Result.Summary.TimeInSeconds;
                }
                times += "\nBus #" + i + ":  " + (temp / 60) + " minutes.";
            }

            canvas1.Visibility = Visibility.Visible;
            textBlock1.Text = times;

            textBox2.Text = "" + (testGenetics.BestScore + 500);




        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {

            testGenetics.run(Int32.Parse(textBox1.Text));
            this.button4_Click(sender, e);
            
            
            
        }

        private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            this.zoomLevel = (int)e.NewValue;
            if (this.testGenetics != null)
            {
                this.button4_Click(sender, e);
            }

            
        }

        private void button3_Click_1(object sender, RoutedEventArgs e)
        {
            offsetX += .005;
            this.button4_Click(sender, e);
        }

        private void button5_Click(object sender, RoutedEventArgs e)
        {
            offsetY -= .005;
            this.button4_Click(sender, e);
        }

        private void button6_Click(object sender, RoutedEventArgs e)
        {
            offsetY += .005;
            this.button4_Click(sender, e);
        }

        private void button4_Click_1(object sender, RoutedEventArgs e)
        {
            offsetX -= .005;
            this.button4_Click(sender, e);
        }

        private void textBox6_TextChanged(object sender, TextChangedEventArgs e)
        {

        }

        private void button7_Click(object sender, RoutedEventArgs e)
        {
            /*
            var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(SmartRoute.Data.Stop[]));
            System.IO.StreamReader temp = new System.IO.StreamReader(@"C:\Documents and Settings\cs480f10_19\Desktop\smartroute2\dev\data\Stops.xml");
            SmartRoute.Data.Stop[] test = (SmartRoute.Data.Stop[])serializer.ReadObject(temp.BaseStream);
            int count = 0;
            for (int i = 0; i < test.Length; i++)
            {
                if (test[i].Passengers > 0)
                {
                    count++;
                }
            }
            IEnumerable<string> addresses =
                from stop in test
                where (stop.Passengers < 0)
                select stop.Address + ", Ellensburg";



            string[] addresses2 = addresses.ToArray();

             */
            //initialize modules used
            

            //bring stops in from XML
            var serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            System.IO.StreamReader temp = new System.IO.StreamReader(@"C:\Documents and Settings\cs480f10_19\Desktop\smartroute\dev\data\Mt. Stuart Elementary School.smrtsch");
            School testSchool1 = (School)serializer.Deserialize(temp.BaseStream);
            IEnumerable<SmartRoute.Data.Stop> stops = testSchool1.Stops;

            IEnumerable<SmartRoute.Data.Stop> activeStops =
                from stop in stops
                where (stop.Passengers > 0)
                select stop;


            List<SmartRoute.Data.Stop> activeStopsList = activeStops.ToList();

            IEnumerable<double> activeLocationsLat =
                from stop in stops
                where (stop.Passengers > 0)
                select stop.Latitude;

            IEnumerable<double> activeLocationsLon =
                from stop in stops
                where (stop.Passengers > 0)
                select stop.Longitude;

            IEnumerable<int> passengers =
                from stop in activeStops
                select stop.Passengers;

            testModule = new DataModule();
            testModule.addBoundary(activeLocationsLon, activeLocationsLat, passengers);
            testGenetics = new Genetics(100, 20, activeStops.Count(), 50, 3600, testModule.accessMap(0));

            testGenetics.setMap(testModule.accessMap(0).Stops);
            testGenetics.setShortestDistanceArray(testModule.accessMap(0).ShortestDistanceArrayTime);

            testGenetics.initializeGeneArray();

            testGenetics.run(1);
        }

        private void button8_Click(object sender, RoutedEventArgs e)
        {
            
        }

        private void textBox2_TextChanged(object sender, TextChangedEventArgs e)
        {

        }

    }
}
